package com.pokermind.dse.tcp.client.interactive;

import com.pokermind.dse.tcp.protocol.ProtocolConstants;
import java.util.*;

/**
 * 交互式扑克客户端主程序 - 脚本对比模式
 * 每一步展示AI决策 vs 预设脚本行动，用户选择采用哪个
 * 
 * @author PokerMind Interactive Client
 */
public class InteractiveClient {
    private static final String DEFAULT_HOST = "127.0.0.1";
    private static final int DEFAULT_PORT = 8889;
    private static final String TABLE_ID = "TABLE_SCENARIO_001";
    
    private final TcpApiClient apiClient;
    private final ActionManager actionManager;
    private final Scanner scanner;
    private final Map<String, Integer> playerActionCount; // 每个玩家在当前街道的行动次数
    
    public InteractiveClient(String host, int port) {
        this.apiClient = new TcpApiClient(host, port);
        this.actionManager = new ActionManager(apiClient);
        this.scanner = new Scanner(System.in);
        this.playerActionCount = new HashMap<>();
    }
    
    public static void main(String[] args) {
        String host = args.length > 0 ? args[0] : DEFAULT_HOST;
        int port = args.length > 1 ? Integer.parseInt(args[1]) : DEFAULT_PORT;
        
        InteractiveClient client = new InteractiveClient(host, port);
        
        try {
            client.run();
        } catch (Exception e) {
            System.err.println("❌ 客户端运行失败: " + e.getMessage());
            e.printStackTrace();
        } finally {
            client.apiClient.close();
        }
    }
    
    public void run() throws Exception {
        // 1. 连接服务器
        apiClient.connect();
        
        // 2. 显示欢迎信息
        System.out.println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
        System.out.println("  PokerMind AI决策 vs 脚本对比测试");
        System.out.println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
        System.out.println("\n场景: 经典BTN vs BB对决");
        System.out.println("  BTN (As Ks) 强牌 + 位置");
        System.out.println("  BB (Qh Jh) 同花连牌 + 位置劣势");
        System.out.println("  Flop: Ah 9h 3c (BB中了坚果同花听牌)");
        System.out.println("  River: Kh (BB完成同花，BTN两对)");
        System.out.println("\n每一步您将看到:");
        System.out.println("  🤖 AI的实时决策建议");
        System.out.println("  📜 预设脚本的标准打法");
        System.out.println("\n按回车键开始...");
        System.out.flush(); // 确保输出
        scanner.nextLine();
        
        // 3. 初始化游戏（使用脚本）
        GameState state = initializeGameWithScript();
        if (state == null) {
            System.out.println("❌ 游戏初始化失败");
            return;
        }
        
        // 显示初始状态并等待用户确认
        UIRenderer.render(state);
        System.out.println("\n✅ 牌局已创建！盲注已下，准备开始行动。");
        System.out.println("   按回车键开始第一轮行动...");
        scanner.nextLine();
        
        // 4. 主游戏循环
        boolean autoMode = false; // 是否切换到自动完成模式
        
        while (!state.isHandComplete()) {
            // 渲染界面
            UIRenderer.render(state);
            
            // 获取当前玩家
            Player currentPlayer = state.getCurrentPlayer();
            if (currentPlayer == null) {
                // 街道结束，转换到下一街
                System.out.println("\n街道结束，准备进入下一街道...");
                Thread.sleep(1500);
                
                if (!transitionToNextStreet(state)) {
                    break;
                }
                playerActionCount.clear(); // 重置行动计数
                continue;
            }
            
            // 统计当前玩家在本街道的行动次数
            String playerKey = currentPlayer.getUserId();
            int actionCount = playerActionCount.getOrDefault(playerKey, 0);
            
            // 执行行动
            boolean success = false;
            
            if (autoMode) {
                // 自动模式：直接采用AI决策并执行
                try {
                    Map<String, Object> aiDecision = actionManager.requestAIAnalysis(state, currentPlayer);
                    if (aiDecision != null) {
                        String aiAction = (String) aiDecision.get("action");
                        String aiSize = String.valueOf(aiDecision.get("size"));
                        int aiAmount = 0;
                        try {
                            aiAmount = Integer.parseInt(aiSize);
                        } catch (Exception e) {
                            aiAmount = 0;
                        }
                        System.out.printf("\n[自动模式] %s %s %d%n", 
                                currentPlayer.getPosition(), aiAction, aiAmount);
                        success = actionManager.recordPlayerAction(state, currentPlayer, aiAction, aiAmount);
                    } else {
                        System.out.println("AI决策失败");
                        success = false;
                    }
                } catch (Exception e) {
                    System.err.println("自动模式失败: " + e.getMessage());
                    success = false;
                }
                Thread.sleep(500);
            } else {
                // 交互模式：显示AI建议，让用户确认
                try {
                    Map<String, Object> aiDecision = actionManager.requestAIAnalysis(state, currentPlayer);
                    
                    if (aiDecision == null) {
                        System.out.println("AI未返回有效决策");
                        success = false;
                    } else {
                        // 安全获取AI决策字段
                        String aiAction = (String) aiDecision.get("action");
                        String aiSize = String.valueOf(aiDecision.get("size"));
                        String aiReasons = (String) aiDecision.get("reasons");
                        if (aiReasons == null || "null".equals(aiReasons)) {
                            aiReasons = (String) aiDecision.get("reason");
                        }
                        
                        // confidence
                        double aiConfidence = 0.0;
                        Object confObj = aiDecision.get("confidence");
                        if (confObj instanceof String) {
                            try {
                                aiConfidence = Double.parseDouble((String) confObj);
                            } catch (NumberFormatException e) {
                                aiConfidence = 0.5;
                            }
                        } else if (confObj instanceof Double) {
                            aiConfidence = (Double) confObj;
                        } else if (confObj instanceof Integer) {
                            aiConfidence = ((Integer) confObj).doubleValue();
                        }
                        
                        // V4.28: 纯AI模式，显示AI建议
                        UIRenderer.printAIDecision(aiAction, aiSize, aiReasons, aiConfidence);
                        
                        // V4.28: 决策质量监控
                        AIDecisionValidator.validateFromMap(aiDecision, state);
                        
                        // 用户选择
                        System.out.println("\n[1]执行 [2]自动 [0]退出");
                        System.out.print("> ");
                        System.out.flush();
                        
                        int choice = getUserChoice();
                        
                        if (choice == 0) {
                            System.out.println("退出游戏");
                            return;
                        } else if (choice == 2) {
                            // 切换到自动模式
                            autoMode = true;
                            System.out.println("已切换到自动模式...");
                            Thread.sleep(500);
                            continue;
                        } else if (choice == 1) {
                            // V4.29: 执行AI建议前的安全检查
                            int aiAmount = 0;
                            try {
                                aiAmount = Integer.parseInt(aiSize);
                            } catch (Exception e) {
                                aiAmount = 0;
                            }
                            
                            // 检查筹码是否足够
                            if (currentPlayer.getStack() <= 0) {
                                System.out.println("⚠️ 筹码不足，强制弃牌");
                                aiAction = "fold";
                                aiAmount = 0;
                            } else if ("raise".equalsIgnoreCase(aiAction) && aiAmount > currentPlayer.getStack()) {
                                // 加注金额超过筹码，改为全下
                                System.out.printf("⚠️ 加注%d超过筹码%d，改为全下%n", aiAmount, currentPlayer.getStack());
                                aiAmount = currentPlayer.getStack();
                            }
                            
                            // 检查是否陷入无限加注循环（翻前最多4轮加注）
                            if ("preflop".equalsIgnoreCase(state.getStreet())) {
                                long raiseCount = state.getActionHistory().stream()
                                        .filter(a -> "raise".equalsIgnoreCase(a.getAction()))
                                        .count();
                                if (raiseCount >= 4 && "raise".equalsIgnoreCase(aiAction)) {
                                    System.out.println("⚠️ 翻前加注轮次过多（" + raiseCount + "轮），强制跟注或弃牌");
                                    // 计算需跟注金额
                                    int maxBet = state.getPlayers().stream()
                                            .mapToInt(Player::getCurrentBet)
                                            .max()
                                            .orElse(0);
                                    int toCall = maxBet - currentPlayer.getCurrentBet();
                                    if (toCall <= currentPlayer.getStack()) {
                                        aiAction = "call";
                                        aiAmount = toCall;
                                    } else {
                                        aiAction = "fold";
                                        aiAmount = 0;
                                    }
                                }
                            }
                            
                            success = actionManager.recordPlayerAction(state, currentPlayer, aiAction, aiAmount);
                        } else {
                            System.out.println("无效选择");
                            success = false;
                        }
                    }
                } catch (Exception e) {
                    System.err.println("处理失败: " + e.getMessage());
                    e.printStackTrace();
                    success = false;
                }
            }
            
            if (success) {
                // 行动成功，增加该玩家的行动计数
                playerActionCount.put(playerKey, actionCount + 1);
                
                // 移动到下一个玩家
                state.moveToNextPlayer();
            } else {
                // 失败直接退出，不重试
                System.out.println("❌ 行动失败，游戏终止");
                System.out.println("   按回车键退出...");
                scanner.nextLine();
                return;
            }
        }
        
        // 完成手牌
        actionManager.completeHand(state);
        UIRenderer.printFinalResult(state);
        
        System.out.println("\n按回车键退出...");
        scanner.nextLine();
    }
    
    /**
     * 使用脚本初始化游戏
     */
    private GameState initializeGameWithScript() throws Exception {
        System.out.println("🃏 正在创建牌局（使用脚本配置）...");
        System.out.flush();
        
        GameState state = new GameState(TABLE_ID, 200, 100);
        state.setStreet("preflop");
        
        // 创建玩家（使用脚本配置的底牌）
        String[] positions = {"SB", "BB", "UTG", "MP", "CO", "BTN"};
        for (int i = 0; i < 6; i++) {
            String userId = "player_" + positions[i].toLowerCase();
            Player player = new Player(userId, positions[i], i + 1, 10000);
            
            // 从脚本获取底牌
            String holeCards = ScenarioScript.ClassicBTNvsBB.getHoleCards(userId);
            player.setHoleCards(holeCards);
            
            state.addPlayer(player);
        }
        
        // 调用服务端创建手牌
        Map<String, Object> request = new HashMap<>();
        String handId = "SCENARIO_H_" + System.currentTimeMillis();
        request.put("hand_id", handId);
        request.put("table_id", TABLE_ID);
        request.put("button_seat", 6);
        request.put("small_blind", state.getSmallBlind());
        request.put("big_blind", state.getBigBlind());
        request.put("ante", 0);
        
        // 构建玩家列表
        List<Map<String, Object>> playerDataList = new ArrayList<>();
        for (Player player : state.getPlayers()) {
            Map<String, Object> playerData = new HashMap<>();
            playerData.put("player_id", player.getUserId());
            playerData.put("position", player.getPosition());
            playerData.put("seat_number", player.getSeatNumber());
            playerData.put("stack", player.getStack());
            playerDataList.add(playerData);
        }
        request.put("players", playerDataList);
        
        System.out.println("📤 发送CREATE_HAND请求...");
        System.out.flush();
        
        Map<String, Object> response = apiClient.sendRequest(
                ProtocolConstants.CREATE_HAND_REQ,
                request
        );
        
        System.out.println("📥 收到响应: " + response);
        System.out.flush();
        
        // 解析响应
        Integer code = (Integer) response.get("code");
        if (code != null && code == 200) {
            @SuppressWarnings("unchecked")
            Map<String, Object> data = (Map<String, Object>) response.get("data");
            if (data != null) {
                String responseHandId = data.containsKey("hand_id") ? 
                        (String) data.get("hand_id") : (String) data.get("handId");
                if (responseHandId != null) {
                    state.setHandId(responseHandId);
                }
            }
            
            if (state.getHandId() == null) {
                state.setHandId(handId);
            }
            
            // 初始化底池（盲注）
            state.setPot(state.getSmallBlind() + state.getBigBlind());
            state.getPlayerByUserId("player_sb").setCurrentBet(state.getSmallBlind());
            state.getPlayerByUserId("player_sb").setStack(10000 - state.getSmallBlind());
            state.getPlayerByUserId("player_bb").setCurrentBet(state.getBigBlind());
            state.getPlayerByUserId("player_bb").setStack(10000 - state.getBigBlind());
            
            // 设置起始行动位置（UTG）
            state.setCurrentPlayerIndex(2);
            
            System.out.println("✅ 手牌创建成功: " + state.getHandId());
            return state;
        } else {
            String desc = (String) response.get("desc");
            System.out.println("❌ 创建手牌失败: " + desc);
            return null;
        }
    }
    
    /**
     * 转换街道
     */
    private boolean transitionToNextStreet(GameState state) throws Exception {
        String nextStreet = getNextStreet(state.getStreet());
        if (nextStreet == null) {
            return false;
        }
        
        // 从脚本获取公共牌
        String boardCardsStr = ScenarioScript.ClassicBTNvsBB.getBoardCards(nextStreet);
        if (boardCardsStr == null || boardCardsStr.isEmpty()) {
            System.out.println("❌ 脚本未定义下一街的公共牌");
            return false;
        }
        
        System.out.printf("🔄 转换街道: %s → %s (%s)%n", 
                state.getStreet(), nextStreet, boardCardsStr);
        
        Map<String, Object> request = new HashMap<>();
        request.put("table_id", state.getTableId());
        request.put("hand_id", state.getHandId());
        request.put("street", nextStreet);
        
        Map<String, Object> response = apiClient.sendRequest(
                ProtocolConstants.TRANSITION_STREET_REQ,
                request
        );
        
        Integer code = (Integer) response.get("code");
        if (code != null && code == 200) {
            @SuppressWarnings("unchecked")
            Map<String, Object> responseData = (Map<String, Object>) response.get("data");
            if (responseData != null) {
                @SuppressWarnings("unchecked")
                List<String> boardCards = (List<String>) responseData.get("board_cards");
                state.transitionToNextStreet(boardCards);
                state.setPot((Integer) responseData.get("pot"));
            }
            
            // V4.27: 显眼的街道转换提示
            System.out.println();
            System.out.println("═".repeat(60));
            System.out.println("    街道转换: " + state.getStreet().toUpperCase() + " | 公共牌: " + String.join(" ", state.getBoard()));
            System.out.println("═".repeat(60));
            System.out.println();
            
            return true;
        } else {
            System.out.println("街道转换失败: " + response.get("desc"));
            return false;
        }
    }
    
    private String getNextStreet(String currentStreet) {
        return switch (currentStreet) {
            case "preflop" -> "flop";
            case "flop" -> "turn";
            case "turn" -> "river";
            default -> null;
        };
    }
    
    /**
     * 获取用户选择
     */
    private int getUserChoice() {
        try {
            String input = scanner.nextLine().trim();
            return Integer.parseInt(input);
        } catch (Exception e) {
            return -1;
        }
    }
}
